package com.middlegroup.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.middlegroup.common.enums.ConfigKeyEnums;
import com.middlegroup.common.exception.ErrorMsg;
import com.middlegroup.common.model.NotifyRequest;
import com.middlegroup.common.model.PayRequest;
import com.middlegroup.common.model.RefundRequestDto;
import com.middlegroup.common.model.TransResult;
import com.middlegroup.common.utils.DateUtils;
import com.middlegroup.pay.dto.*;
import com.middlegroup.pay.entity.*;
import com.middlegroup.pay.service.*;
import com.middlegroup.pay.utils.Base64Utils;
import com.middlegroup.pay.utils.HttpUtil;
import com.middlegroup.pay.utils.XmlUtils;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;

import static com.middlegroup.common.enums.ConfigKeyEnums.url;

/**
 * Created by pc on 2019/1/14.
 */
@Service
@Slf4j
public class WechatPayH5ServiceImpl implements WechatPayH5Service {
    @Resource
    private ThirdBillsService thirdBillsService;
    @Resource
    private SystemCfgService systemCfgService;
    @Resource
    private InBillsService inBillsService;
    @Resource
    private InNotifyLogService inNotifyLogService;
    @Resource
    private RefundBillsService refundBillsService;
    @Resource
    private OutNotifyLogService outNotifyLogService;
    @Resource
    private NotifyMerchantService notifyMerchantService;

    /**
     * 统一下单, H5支付(MWEB).
     *
     * @return 支付跳转链接
     * <p> mweb_url为拉起微信支付收银台的中间页面，可通过访问该url来拉起微信客户端，完成支付,mweb_url的有效期为5分钟。
     */
    @Override
    public TransResult wechatPayH5(PayRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        String category = request.getChannelCode().getCode();

        String appid = systemCfgService.getConfigString(category, ConfigKeyEnums.appid.getName());
        String mch_id = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_id.getName());
        String mch_key = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_key.getName());
        String notify_url = systemCfgService.getConfigString(category, ConfigKeyEnums.notify_url.getName());
        String wap_url = systemCfgService.getConfigString(category, ConfigKeyEnums.wap_url.getName());
        String requestUrl = systemCfgService.getConfigString(category, url.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(appid) || StringUtils.isBlank(mch_id)
                || StringUtils.isBlank(mch_key) || StringUtils.isBlank(notify_url) || StringUtils.isBlank(wap_url)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        // 请求参数
        WechatPayRequest wechatPayRequest = new WechatPayRequest();
        wechatPayRequest.setAppid(appid);
        wechatPayRequest.setMch_id(mch_id);
        wechatPayRequest.setNonce_str(generateNonceStr());
        wechatPayRequest.setBody(request.getSubject());
        wechatPayRequest.setOut_trade_no(request.getBillNo());
        wechatPayRequest.setFee_type(request.getTransCurrency());
        wechatPayRequest.setTotal_fee(request.getAmount().multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP).toString());
        wechatPayRequest.setSpbill_create_ip(request.getIp());
        wechatPayRequest.setTime_start(DateUtils.convert(new Date(), DateUtils.DATE_TIMESTAMP_SHORT_FORMAT));
        wechatPayRequest.setTime_expire(DateUtils.convert(new Date(System.currentTimeMillis() + 5 * 60 * 1000),
                DateUtils.DATE_TIMESTAMP_SHORT_FORMAT));
        wechatPayRequest.setNotify_url(notify_url);
        wechatPayRequest.setScene_info("{\"h5_info\":{\"type\":\"Wap\",\"wap_url\":" + wap_url + ",\"wap_name\": \"booming\"}");
        // 请求签名
        Map<String, Object> objectMap = XmlUtils.beanToMap(wechatPayRequest);
        String sign = this.generateSignatureObj(objectMap, mch_key);
        if (StringUtils.isBlank(sign)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置签名
        wechatPayRequest.setSign(sign);
        // xml格式
        String xml = XmlUtils.toXml(wechatPayRequest);
        xml = StringEscapeUtils.unescapeXml(xml);
        log.debug("微信H5支付请求参数：{}", xml);
        ThirdBills thirdBills = new ThirdBills();
        thirdBills.setMethod("wechatPayH5");
        thirdBills.setSubjectCode(request.getSubjectCode());
        thirdBills.setMerchantBillNo(request.getMerchantBillNo());
        thirdBills.setBillNo(request.getBillNo());
        thirdBills.setStatus(0);
        thirdBills.setAmount(request.getAmount());
        thirdBills.setRequestUrl(requestUrl);
        thirdBills.setRequestText(xml);
        thirdBills.setBeginTime(System.currentTimeMillis());
        thirdBills.setCurrency(request.getTransCurrency());//币种

        String str = null;
        try {
            // TODO restTemplate.postForObject() 对微信请求方式有问题，临时改http 后续需要改的自己手动修改其他方式
            // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
            str = HttpUtil.postData(requestUrl, xml, "application/xml");
            log.debug("支付结果返回结果：{}", str);
        } catch (Exception e) {
            log.error("调用微信h5支付统一下单接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        // 返回结果保存
        thirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        thirdBills.setEndTime(System.currentTimeMillis());
        if (StringUtils.isBlank(str)) {
            // 默认处理中
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_RETURN_BLANK);
        } else {
            // 返回结果
            WechatResponse wechatResponse = XmlUtils.xml2Bean(str, WechatResponse.class);
            log.debug("微信支付接口返回结果：{}", wechatResponse);
            if (wechatResponse != null && StringUtils.equals("SUCCESS", wechatResponse.getReturn_code())) {

                // 开始签名
                Map<String, Object> resultMap = XmlUtils.beanToMap(wechatResponse);
                String returnSign = generateSignatureObj(resultMap, mch_key);
                if (returnSign == null || !StringUtils.equals(returnSign, wechatResponse.getSign())) {
                    // 签名失败
                    transResult.setTransStatus(2);
                    thirdBills.setStatus(2);
                    transResult.setMsg(ErrorMsg.RETURN_DATA_CHECK_SIGN_FAIL);
                } else {
                    // 成功处理
                    String resultCode = wechatResponse.getResult_code();
                    if (StringUtils.equals("SUCCESS", resultCode)) {
                        transResult.setTransStatus(0);
                        transResult.setNextStepData(wechatResponse.getMweb_url());  //支付跳转链接
                        transResult.setTransNo(wechatResponse.getPrepay_id());//预支付交易会话标识
                        thirdBills.setStatus(0);
                        thirdBills.setTransNo(wechatResponse.getPrepay_id());
                    } else {
                        //交易失败
                        transResult.setTransStatus(2);
                        thirdBills.setStatus(2);
                        transResult.setMsg(wechatResponse.getErr_code_des());
                    }
                }
            } else {
                // 失败处理
                transResult.setTransStatus(2);
                thirdBills.setStatus(2);
                transResult.setMsg(wechatResponse.getReturn_msg());
            }
        }
        try {
            thirdBillsService.insert(thirdBills);
        } catch (Exception e) {
            log.error("微信h5支付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }

    /**
     * 订单查询
     */
    @Override
    public TransResult wechatPayH5Query(PayRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        if (StringUtils.isBlank(request.getMerchantBillNo())) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.EMPTY_MERCHANTBILLNO);
            return transResult;
        }
        if (StringUtils.isBlank(request.getBillNo())) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.EMPTY_BILLNO);
            return transResult;
        }
        if (StringUtils.isBlank(request.getSubjectCode())) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.EMPTY_SUBJECTCODE);
            return transResult;
        }
        if (StringUtils.isBlank(request.getMerchantCode())) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.EMPTY_MERCHANTCODE);
            return transResult;
        }

        InBills inBills = inBillsService.getByMerchantBillNo(request.getMerchantBillNo());
        if (null == inBills) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.BILLSNOTFOUND_OR_STATUSFAIL);
            return transResult;
        }
        if (1 == inBills.getStatus().intValue() || 2 == inBills.getStatus().intValue()) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.BILLSNOTFOUND_OR_STATUSFAIL);
            return transResult;
        }

        String category = inBills.getChannelCode();

        String appid = systemCfgService.getConfigString(category, ConfigKeyEnums.appid.getName());
        String mch_id = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_id.getName());
        String mch_key = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_key.getName());
        String notify_url = systemCfgService.getConfigString(category, ConfigKeyEnums.notify_url.getName());
        String wap_url = systemCfgService.getConfigString(category, ConfigKeyEnums.wap_url.getName());
        String requestUrl = systemCfgService.getConfigString(category, ConfigKeyEnums.orderquery_url.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(appid) || StringUtils.isBlank(mch_id)
                || StringUtils.isBlank(mch_key) || StringUtils.isBlank(notify_url) || StringUtils.isBlank(wap_url)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        // 请求参数
        WechatPayRequest wechatPayRequest = new WechatPayRequest();
        wechatPayRequest.setAppid(appid);
        wechatPayRequest.setMch_id(mch_id);
        wechatPayRequest.setNonce_str(generateNonceStr());
        wechatPayRequest.setLimit_pay(null);
        wechatPayRequest.setTrade_type(null);
        wechatPayRequest.setOut_trade_no(inBills.getBillNo()); // 商户订单号
        // 请求签名
        Map<String, Object> objectMap = XmlUtils.beanToMap(wechatPayRequest);
        String sign = this.generateSignatureObj(objectMap, mch_key);
        if (StringUtils.isBlank(sign)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置签名
        wechatPayRequest.setSign(sign);

        // xml格式转化
        String xml = XmlUtils.toXml(wechatPayRequest);
        log.debug("微信订单查询请求参数：{}", xml);
        ThirdBills thirdBills = new ThirdBills();
        thirdBills.setMethod("wechatPayH5Query");
        thirdBills.setSubjectCode(inBills.getSubjectCode());
        thirdBills.setMerchantBillNo(inBills.getMerchantBillNo());
        thirdBills.setBillNo(inBills.getBillNo());
        thirdBills.setStatus(0);
        thirdBills.setAmount(inBills.getAmount());
        thirdBills.setRequestUrl(requestUrl);
        thirdBills.setRequestText(xml);
        thirdBills.setBeginTime(System.currentTimeMillis());
        thirdBills.setCurrency(inBills.getCurrency());

        String str = null;
        try {
            // https://api.mch.weixin.qq.com/pay/orderquery
            //str = restTemplate.postForObject(requestUrl,xml,String.class);
            str = HttpUtil.postData(requestUrl, xml, "application/xml");
        } catch (Exception e) {
            log.error("调用微信h5支付订单查询接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        log.debug("微信订单查询返回结果：{}", str);
        thirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        thirdBills.setEndTime(System.currentTimeMillis());

        // 处理返回为空
        if (StringUtils.isBlank(str)) {
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_RETURN_BLANK);
        } else {
            // 查询结果
            WechatQueryOrderResponse wechatQueryOrderResponse = XmlUtils.xml2Bean(str, WechatQueryOrderResponse.class);
            log.debug("微信支付状态查询接口返回结果：{}", wechatQueryOrderResponse);
            if (wechatQueryOrderResponse != null && StringUtils.equals("SUCCESS", wechatQueryOrderResponse.getReturn_code())) {
                // 开始签名
                Map<String, Object> resultMap = XmlUtils.beanToMap(wechatQueryOrderResponse);
                String returnSign = generateSignatureObj(resultMap, mch_key);
                if (returnSign == null || !StringUtils.equals(returnSign, wechatQueryOrderResponse.getSign())) {
                    // 签名失败
                    transResult.setTransStatus(2);
                    thirdBills.setStatus(2);
                    transResult.setMsg(ErrorMsg.RETURN_DATA_CHECK_SIGN_FAIL);
                } else {
                    // 成功处理
                    String resultCode = wechatQueryOrderResponse.getResult_code();
                    if (StringUtils.equals("SUCCESS", resultCode)) {
                        //交易状态 SUCCESS—支付成功 REFUND—转入退款 NOTPAY—未支付 CLOSED—已关闭
                        // REVOKED—已撤销(刷卡支付) USERPAYING--用户支付中 PAYERROR--支付失败(其他原因，如银行返回失败)
                        String tradeState = wechatQueryOrderResponse.getTrade_state();
                        if (StringUtils.equals("SUCCESS", tradeState) || StringUtils.equals("REFUND", tradeState)) {
                            // 支付成功
                            thirdBills.setStatus(1);
                            transResult.setTransStatus(1);
                        } else if (StringUtils.equals("USERPAYING", tradeState)) {
                            // 支付中
                            thirdBills.setStatus(0);
                            transResult.setTransStatus(0);
                        } else {
                            //其他情况支付失败
                            thirdBills.setStatus(2);
                            transResult.setTransStatus(2);
                        }
                        String transactionId = wechatQueryOrderResponse.getTransaction_id();
                        //订单支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
                        String timeEnd = wechatQueryOrderResponse.getTime_end();
                        thirdBills.setTransNo(transactionId);
                        transResult.setTransNo(transactionId);
                        if (StringUtils.isNotBlank(timeEnd)) {
                            transResult.setTransTime(DateUtils.convert(timeEnd, DateUtils.DATE_TIMESTAMP_SHORT_FORMAT).getTime());
                        }
                    } else {
                        //交易失败
                        transResult.setTransStatus(2);
                        thirdBills.setStatus(2);
                        transResult.setMsg(wechatQueryOrderResponse.getErr_code_des());
                    }
                }
            } else {
                // 失败处理
                transResult.setTransStatus(2);
                thirdBills.setStatus(2);
                transResult.setMsg(wechatQueryOrderResponse.getReturn_msg());
            }
        }

        if (transResult.getTransStatus().intValue() == 1 || transResult.getTransStatus().intValue() == 2) {
            inBills.setStatus(transResult.getTransStatus());
            inBills.setOrderId(transResult.getTransNo());
            inBills.setPayTime(transResult.getTransTime());
            inBillsService.updateById(inBills);
        }

        try {
            thirdBillsService.insert(thirdBills);
        } catch (Exception e) {
            log.error("微信h5支付订单查询插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }

    /**
     * 退款
     */
    @Override
    public TransResult wechatPayH5Refund(RefundRequestDto request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getRefundAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        InBills inBills = inBillsService.getByMerchantBillNo(request.getMerchantBillNo());

        String category = inBills.getChannelCode();

        String appid = systemCfgService.getConfigString(category, ConfigKeyEnums.appid.getName());
        String mch_id = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_id.getName());
        String mch_key = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_key.getName());
        String wap_url = systemCfgService.getConfigString(category, ConfigKeyEnums.wap_url.getName());
        String requestUrl = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_url.getName());
        String refund_notify_url = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_notify_url.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(appid) || StringUtils.isBlank(mch_id)
                || StringUtils.isBlank(mch_key) || StringUtils.isBlank(wap_url) || StringUtils.isBlank(refund_notify_url)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        // 请求参数
        WechatPayRequest wechatPayRequest = new WechatPayRequest();
        wechatPayRequest.setAppid(appid);
        wechatPayRequest.setMch_id(mch_id);
        wechatPayRequest.setNonce_str(generateNonceStr());
        wechatPayRequest.setLimit_pay(null);
        wechatPayRequest.setTrade_type(null);
        wechatPayRequest.setOut_trade_no(inBills.getBillNo()); // 商户订单号
        wechatPayRequest.setOut_refund_no(request.getBillNo());//商户退款单号
        wechatPayRequest.setTotal_fee(inBills.getAmount().multiply(new BigDecimal(100)).intValue() + "");
        wechatPayRequest.setRefund_fee(request.getRefundAmount().multiply(new BigDecimal(100)).intValue() + "");
        wechatPayRequest.setNotify_url(refund_notify_url);
        wechatPayRequest.setRefund_fee_type(inBills.getCurrency());
        // 请求签名
        Map<String, Object> objectMap = XmlUtils.beanToMap(wechatPayRequest);
        String sign = this.generateSignatureObj(objectMap, mch_key);
        if (StringUtils.isBlank(sign)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置签名
        wechatPayRequest.setSign(sign);

        // xml格式转化
        String xml = XmlUtils.toXml(wechatPayRequest);
        log.debug("微信订单退款请求参数：{}", xml);
        ThirdBills thirdBills = new ThirdBills();
        thirdBills.setMethod("wechatPayH5Refund");
        thirdBills.setSubjectCode(inBills.getSubjectCode());
        thirdBills.setMerchantBillNo(inBills.getMerchantBillNo());
        thirdBills.setBillNo(inBills.getBillNo());
        thirdBills.setStatus(0);
        thirdBills.setAmount(request.getRefundAmount());
        thirdBills.setRequestUrl(requestUrl);
        thirdBills.setRequestText(JSON.toJSONString(wechatPayRequest));
        thirdBills.setBeginTime(System.currentTimeMillis());
        thirdBills.setCurrency(inBills.getCurrency());

        String str = null;
        try {
            // TODO 需要证书
            // https://api.mch.weixin.qq.com/secapi/pay/refund
            str = this.doRefund(requestUrl, xml, mch_id);
//            str = HttpUtil.postData(requestUrl, xml, "application/xml");
        } catch (Exception e) {
            log.error("调用微信h5退款接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        log.debug("微信退款返回结果：{}", str);
        thirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        thirdBills.setEndTime(System.currentTimeMillis());
        // 返回为空处理
        if (StringUtils.isBlank(str)) {
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_RETURN_BLANK);
        } else {
            // 结果处理
            WechatRefundOrderResponse wechatRefundOrder = XmlUtils.xml2Bean(str, WechatRefundOrderResponse.class);
            if (wechatRefundOrder != null && StringUtils.equals("SUCCESS", wechatRefundOrder.getReturn_code())) {
                // 构建签名参数
                Map<String, Object> resultMap = XmlUtils.beanToMap(wechatRefundOrder);
                String returnSign = generateSignatureObj(resultMap, mch_key);
                if (returnSign == null || !StringUtils.equals(returnSign, wechatRefundOrder.getSign())) {
                    // 签名失败
                    transResult.setTransStatus(0);
                    thirdBills.setStatus(0);
                    transResult.setMsg(ErrorMsg.RETURN_DATA_CHECK_SIGN_FAIL);
                } else {
                    // 处理成功情况
                    if (StringUtils.equals("SUCCESS", wechatRefundOrder.getResult_code())) {
                        //微信退款单号
                        String refund_id = wechatRefundOrder.getRefund_id();
                        transResult.setTransStatus(0);
                        transResult.setTransNo(refund_id);
                        thirdBills.setStatus(0);
                        thirdBills.setTransNo(refund_id);
                        transResult.setMsg(ErrorMsg.REFUND_SUCCESS);
                    } else {
                        //交易失败
                        transResult.setTransStatus(2);
                        thirdBills.setStatus(2);
                        transResult.setMsg(wechatRefundOrder.getErr_code_des());
                    }
                }

            } else {
                //交易失败
                transResult.setTransStatus(2);
                thirdBills.setStatus(2);
                transResult.setMsg(wechatRefundOrder.getReturn_msg());
            }
        }
        try {
            thirdBillsService.insert(thirdBills);
        } catch (Exception e) {
            log.error("微信h5退款插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }


    /**
     * 退款订单查询
     */
    @Override
    public TransResult wechatPayH5RefundQuery(String merchantBillNo) {
        TransResult transResult = new TransResult();
        transResult.setMerchantBillNo(merchantBillNo);
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        if (StringUtils.isBlank(merchantBillNo)) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.EMPTY_MERCHANTBILLNO);
            return transResult;
        }

        RefundBills refundBills = refundBillsService.getByMBillNo(merchantBillNo);
        if (null == refundBills) {
            transResult.setTransStatus(0);
            transResult.setMsg("退款订单不存在！");
            return transResult;
        }
        if (1 == refundBills.getStatus().intValue() || 2 == refundBills.getStatus().intValue()) {
            transResult.setTransStatus(0);
            transResult.setMsg(ErrorMsg.BILLSNOTFOUND_OR_STATUSFAIL);
            return transResult;
        }
        transResult.setAmount(refundBills.getAmount());

        String category = refundBills.getServiceType();

        String appid = systemCfgService.getConfigString(category, ConfigKeyEnums.appid.getName());
        String mch_id = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_id.getName());
        String mch_key = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_key.getName());
        String notify_url = systemCfgService.getConfigString(category, ConfigKeyEnums.notify_url.getName());
        String wap_url = systemCfgService.getConfigString(category, ConfigKeyEnums.wap_url.getName());
        String requestUrl = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_orderquery_url.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(appid) || StringUtils.isBlank(mch_id)
                || StringUtils.isBlank(mch_key) || StringUtils.isBlank(notify_url) || StringUtils.isBlank(wap_url)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }
        // 请求参数
        WechatPayRequest wechatPayRequest = new WechatPayRequest();
        wechatPayRequest.setAppid(appid);
        wechatPayRequest.setMch_id(mch_id);
        wechatPayRequest.setNonce_str(generateNonceStr());
        wechatPayRequest.setLimit_pay(null);
        wechatPayRequest.setTrade_type(null);
        wechatPayRequest.setOut_refund_no(refundBills.getRefundNo());
        // 请求签名
        Map<String, Object> objectMap = XmlUtils.beanToMap(wechatPayRequest);
        String sign = this.generateSignatureObj(objectMap, mch_key);
        if (StringUtils.isBlank(sign)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置签名
        wechatPayRequest.setSign(sign);

        // xml格式转化
        String xml = XmlUtils.toXml(wechatPayRequest);
        log.debug("微信订单退款查询请求参数：{}", xml);
        ThirdBills thirdBills = new ThirdBills();
        thirdBills.setMethod("wechatPayH5RefundQuery");
        thirdBills.setSubjectCode(refundBills.getSubjectCode());
        thirdBills.setMerchantBillNo(refundBills.getMerchantBillNo());
        thirdBills.setBillNo(refundBills.getRefundNo());
        thirdBills.setStatus(0);
        thirdBills.setAmount(refundBills.getAmount());
        thirdBills.setRequestUrl(requestUrl);
        thirdBills.setRequestText(JSON.toJSONString(wechatPayRequest));
        thirdBills.setBeginTime(System.currentTimeMillis());
//        thirdBills.setCurrency(refundBills.getCurrency());

        String str = null;
        try {
            // https://api.mch.weixin.qq.com/pay/refundquery
            //str = restTemplate.postForObject(requestUrl,xml,String.class);
            str = HttpUtil.postData(requestUrl, xml, "application/xml");
        } catch (Exception e) {
            log.error("调用微信h5支付退款订单查询接口异常,merchantBillNo:{},error:{}", merchantBillNo, e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        log.debug("微信退款查询返回结果：{}", str);
        thirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        thirdBills.setEndTime(System.currentTimeMillis());
        if (StringUtils.isBlank(str)) {
            //默认交易处理中
            log.error("调用微信h5支付退款订单查询接口返回空,merchantBillNo:{}", merchantBillNo);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_RETURN_BLANK);
        } else {
            // 返回结果处理
            WechatRefundQueryResponse wechatRefundQuery = XmlUtils.xml2Bean(str, WechatRefundQueryResponse.class);
            if (wechatRefundQuery != null && StringUtils.equals("SUCCESS", wechatRefundQuery.getReturn_code())) {
                // 结果签名
                Map<String, Object> resultMap = XmlUtils.beanToMap(wechatRefundQuery);
                String returnSign = generateSignatureObj(resultMap, mch_key);
                if (returnSign == null || !StringUtils.equals(returnSign, wechatRefundQuery.getSign())) {
                    // 签名失败
                    transResult.setTransStatus(0);
                    thirdBills.setStatus(0);
                    transResult.setMsg(ErrorMsg.RETURN_DATA_CHECK_SIGN_FAIL);
                } else {
                    // 处理成功情况
                    if (StringUtils.equals("SUCCESS", wechatRefundQuery.getResult_code())) {
                        //退款状态：SUCCESS—退款成功 REFUNDCLOSE—退款关闭 PROCESSING—退款处理中
                        // CHANGE—退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，
                        // 可前往商户平台（pay.weixin.qq.com）-交易中心，手动处理此笔退款。$n为下标，从0开始编号。
                        String tradeState = wechatRefundQuery.getRefund_status_0();
                        if (StringUtils.equals("SUCCESS", tradeState) || StringUtils.equals("REFUND", tradeState)) {
                            //退款成功
                            thirdBills.setStatus(1);
                            transResult.setTransStatus(1);
                            refundBills.setMsg(ErrorMsg.REFUND_SUCCESS);
                        } else if (StringUtils.equals("PROCESSING", tradeState)) {
                            //退款处理中
                            thirdBills.setStatus(0);
                            transResult.setTransStatus(0);
                        } else {
                            //其他退款失败
                            thirdBills.setStatus(2);
                            transResult.setTransStatus(2);
                            refundBills.setMsg(ErrorMsg.REFUND_FAIL);
                        }
                        //微信退款单号
                        String refundId = wechatRefundQuery.getRefund_id_0();
                        //退款成功时间，2016-07-25 15:26:26	退款成功时间，当退款状态为退款成功时有返回。$n为下标，从0开始编号。
                        String timeEnd = wechatRefundQuery.getRefund_success_time_0();
                        thirdBills.setTransNo(refundId);
                        transResult.setTransNo(refundId);
                        if (StringUtils.isNotBlank(timeEnd)) {
                            transResult.setTransTime(DateUtils.convert(timeEnd, DateUtils.DATE_TIME_FORMAT).getTime());
                        }
                    } else {
                        //交易失败
                        transResult.setTransStatus(2);
                        thirdBills.setStatus(2);
                        refundBills.setMsg(ErrorMsg.REFUND_FAIL);
                        transResult.setMsg(wechatRefundQuery.getErr_code_des());
                    }
                }
            } else {
                //交易失败
                transResult.setTransStatus(2);
                thirdBills.setStatus(2);
                refundBills.setMsg(ErrorMsg.REFUND_FAIL);
                transResult.setMsg(wechatRefundQuery.getReturn_msg());
            }
        }

        if (transResult.getTransStatus().intValue() == 1 || transResult.getTransStatus().intValue() == 2) {
            refundBills.setStatus(transResult.getTransStatus());
            refundBills.setRefundTime(transResult.getTransTime());
            refundBillsService.updateById(refundBills);
        }

        try {
            thirdBillsService.insert(thirdBills);
        } catch (Exception e) {
            log.error("微信h5支付退款订单查询插入第三方订单表异常,merchantBillNo:{},error:{}",merchantBillNo, e);
        }

        return transResult;
    }


    /**
     * 微信支付回调
     */
    @Override
    public String wechatPayH5Notify(HttpServletRequest request) throws Exception {
        log.info("wechatPayH5Notify, 进入异步通知接口...");
        // 获取异步通知参数
        String callbackXml = parseWeixinCallback(request);
        if (StringUtils.isBlank(callbackXml)) {
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "未获取通知参数"));
        }

        InNotifyLog inNotifyLog = new InNotifyLog();
        inNotifyLog.setCallbackText(callbackXml);
        inNotifyLog.setStatus(0);
        inNotifyLog.setTransStatus(0);

        String category = "wx_h5";
        String appid = systemCfgService.getConfigString(category, ConfigKeyEnums.appid.getName());
        String mch_id = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_id.getName());
        String mch_key = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_key.getName());
        String wap_url = systemCfgService.getConfigString(category, ConfigKeyEnums.wap_url.getName());
        String requestUrl = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_url.getName());
        String refund_notify_url = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_notify_url.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(appid) || StringUtils.isBlank(mch_id)
                || StringUtils.isBlank(mch_key) || StringUtils.isBlank(wap_url) || StringUtils.isBlank(refund_notify_url)) {
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "获取配置信息异"));
        }
        // 返回结果封装
        WechatCallBackInfo wechatCallBackInfo = new WechatCallBackInfo();
        // 查询结果
        WechatQueryOrderResponse wechatQueryOrderResponse = XmlUtils.xml2Bean(callbackXml, WechatQueryOrderResponse.class);
        log.debug("微信支付回调接口返回结果：{}", wechatQueryOrderResponse);
        if (wechatQueryOrderResponse != null && StringUtils.equals("SUCCESS", wechatQueryOrderResponse.getReturn_code())) {
            // 获取订单号
            String outTradeNo = wechatQueryOrderResponse.getOut_trade_no();
            inNotifyLog.setBillNo(outTradeNo);
            inNotifyLog.setStatus(1);
            InBills inBills = inBillsService.getByBillNo(outTradeNo);
            if (inBills != null && (inBills.getStatus() == 0 || inBills.getStatus() == 3)) {
                inNotifyLog.setMerchantBillNo(inBills.getMerchantBillNo());
                // 构建签名参数
                Map<String, Object> resultMap = XmlUtils.beanToMap(wechatQueryOrderResponse);
                String returnSign = generateSignatureObj(resultMap, mch_key);
                // 签名对比
                if (returnSign != null && StringUtils.equals(returnSign, wechatQueryOrderResponse.getSign())) {
                    // 业务结果 SUCCESS/FAIL
                    String resultCode = wechatQueryOrderResponse.getResult_code();
                    if (StringUtils.equals("SUCCESS", resultCode)) {
                        // 支付成功
                        inBills.setStatus(1);
                    }else {
                        //其他情况支付失败
                        inBills.setStatus(2);
                    }
                    //订单支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
                    String timeEnd = wechatQueryOrderResponse.getTime_end();
                    if (StringUtils.isNotBlank(timeEnd)) {
                        inBills.setPayTime(DateUtils.convert(timeEnd, DateUtils.DATE_TIMESTAMP_SHORT_FORMAT).getTime());
                    }

                    String transactionId = wechatQueryOrderResponse.getTransaction_id();
                    inBills.setOrderId(transactionId);
                    wechatCallBackInfo.setReturnCode("SUCCESS");
                    wechatCallBackInfo.setReturnMsg("OK");
                    inNotifyLog.setTransNo(transactionId);
                    inNotifyLog.setTransStatus(inBills.getStatus());
                    // 更新状态
                    inBillsService.updateById(inBills);

                    //TODO 通知 booming
                    if(StringUtils.isNotEmpty(inBills.getNotifyUrl()) && (inBills.getStatus().intValue()==1 || inBills.getStatus().intValue()==2)) {
                        NotifyRequest notifyRequest = new NotifyRequest();
                        notifyRequest.setMerchantBillNo(inBills.getMerchantBillNo());
                        notifyRequest.setBillNo(inBills.getBillNo());
                        notifyRequest.setStatus(inBills.getStatus());
                        notifyRequest.setMsg("微信支付回调");
                        notifyRequest.setType(1);
                        notifyRequest.setTransTime(inBills.getPayTime());//交易时间
                        notifyMerchantService.postMerchant(notifyRequest, inBills.getNotifyUrl(), inBills.getMerchantCode());//通知给商家
                    }
                }else {
                    // 验签失败
                    wechatCallBackInfo.setReturnCode("Fail");
                    wechatCallBackInfo.setReturnMsg("验签失败");
                }
            }else {
                wechatCallBackInfo.setReturnCode("Fail");
                wechatCallBackInfo.setReturnMsg("订单不存在或定单状态已确定");
            }
        } else {
            // 返回结果解释失败
            wechatCallBackInfo.setReturnCode("Fail");
            wechatCallBackInfo.setReturnMsg("返回结果解析失败");
        }

        inNotifyLog.setResponseText(JSON.toJSONString(wechatCallBackInfo));
        //插入日志表
        inNotifyLogService.insert(inNotifyLog);
        // 返回结果
        return XmlUtils.toXml(wechatCallBackInfo);
    }

    @Override
    public String wechatH5RefundNotify(HttpServletRequest request) throws Exception {
        log.info("wechatH5RefundNotify, 进入异步通知接口...");
        // 获取异步通知参数
        String callbackXml = parseWeixinCallback(request);
        log.debug("微信退款第三方异步通知：{}",callbackXml);
        if (StringUtils.isBlank(callbackXml)) {
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "未获取通知参数"));
        }

        OutNotifyLog outNotifyLog = new OutNotifyLog();
        outNotifyLog.setCallbackText(callbackXml);
        outNotifyLog.setStatus(0);
        outNotifyLog.setTransStatus(0);
        outNotifyLogService.insert(outNotifyLog);
        String category = "wx_h5";
        String appid = systemCfgService.getConfigString(category, ConfigKeyEnums.appid.getName());
        String mch_id = systemCfgService.getConfigString(category, ConfigKeyEnums.mch_id.getName());
        String refund_mch_key = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_mch_key.getName());
        String wap_url = systemCfgService.getConfigString(category, ConfigKeyEnums.wap_url.getName());
        String requestUrl = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_url.getName());
        String refund_notify_url = systemCfgService.getConfigString(category, ConfigKeyEnums.refund_notify_url.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(appid) || StringUtils.isBlank(mch_id)
                || StringUtils.isBlank(refund_mch_key) || StringUtils.isBlank(wap_url) || StringUtils.isBlank(refund_notify_url)) {
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "获取配置信息异"));
        }
        // 返回结果封装
        WechatRefundCallBack wechatRefundCallBack = XmlUtils.xml2Bean(callbackXml, WechatRefundCallBack.class);
        if (!StringUtils.equals("SUCCESS", wechatRefundCallBack.getReturn_code())) {
            outNotifyLog.setResponseText(JSON.toJSONString(new WechatCallBackInfo("Fail", "通知状态异常")));
            //插入日志表
            outNotifyLogService.updateById(outNotifyLog);
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "通知状态异常"));
        }
        //Security.addProvider(new BouncyCastleProvider());
        String result = this.decryptData(wechatRefundCallBack.getReq_info(), refund_mch_key);
        if (StringUtils.isBlank(result)) {
            outNotifyLog.setResponseText(JSON.toJSONString(new WechatCallBackInfo("Fail", "解密失败")));
            //插入日志表
            outNotifyLogService.updateById(outNotifyLog);
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "解密失败"));
        }
        // 结果
        WechatRefundCallBackResponse wechatRefundCallBackInfo = XmlUtils.xml2Bean(result, WechatRefundCallBackResponse.class);
        if (wechatRefundCallBackInfo == null || StringUtils.isBlank(wechatRefundCallBackInfo.getRefundStatus())) {
            outNotifyLog.setResponseText(JSON.toJSONString(new WechatCallBackInfo("Fail", "返回状态异常")));
            //插入日志表
            outNotifyLogService.updateById(outNotifyLog);
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "返回状态异常"));
        }
        // 获取订单号
        String refundNo = wechatRefundCallBackInfo.getOutFefundNo();
        outNotifyLog.setMerchantBillNo(refundNo);
        outNotifyLog.setStatus(1);
        outNotifyLog.setTransNo(wechatRefundCallBackInfo.getRefundId());

        RefundBills refundBills = refundBillsService.getByRefundNo(refundNo);
        if (refundBills != null && (refundBills.getStatus() == 0 || refundBills.getStatus() == 3)) {
            outNotifyLog.setBillNo(refundBills.getRefundNo());
            //SUCCESS-退款成功 CHANGE-退款异常 REFUNDCLOSE—退款关闭
            if(("SUCCESS").equals(wechatRefundCallBackInfo.getRefundStatus())){
                refundBills.setStatus(1);
            }else {
                refundBills.setStatus(2);
            }
            //资金退款至用户帐号的时间，格式2017-12-15 09:46:01
            String timeEnd = wechatRefundCallBackInfo.getSuccessTime();
            if (StringUtils.isNotBlank(timeEnd)) {
                refundBills.setRefundTime(DateUtils.convert(timeEnd, DateUtils.DATE_TIME_FORMAT).getTime());
            }

            refundBills.setOutRequestNo(wechatRefundCallBackInfo.getRefundId());
            // 更新状态
            refundBillsService.updateById(refundBills);

            //TODO 通知booming
            if(StringUtils.isNotEmpty(refundBills.getNotifyUrl()) && (refundBills.getStatus().intValue()==1 || refundBills.getStatus().intValue()==2)) {
                NotifyRequest notifyRequest = new NotifyRequest();
                notifyRequest.setMerchantBillNo(refundBills.getMerchantBillNo());
                notifyRequest.setMerchantRefundNo(refundBills.getMerchantRefundNo());
                notifyRequest.setStatus(refundBills.getStatus());
                notifyRequest.setMsg("微信退款回调");
                notifyRequest.setType(1);
                notifyRequest.setTransTime(refundBills.getRefundTime());//交易时间
                notifyMerchantService.postMerchant(notifyRequest, refundBills.getNotifyUrl(), refundBills.getMerchantCode());//通知给商家
            }

        }else {
            outNotifyLog.setResponseText(JSON.toJSONString(new WechatCallBackInfo("Fail", "订单不存在或定单状态已确定")));
            //插入日志表
            outNotifyLogService.updateById(outNotifyLog);
            return XmlUtils.toXml(new WechatCallBackInfo("Fail", "订单不存在或定单状态已确定"));
        }
        outNotifyLog.setTransStatus(refundBills.getStatus());
        outNotifyLog.setResponseText(JSON.toJSONString(new WechatCallBackInfo("SUCCESS", "OK")));
        //插入日志表
        outNotifyLogService.updateById(outNotifyLog);
        return XmlUtils.toXml(new WechatCallBackInfo("SUCCESS", "OK"));
    }

    /**
     * AES解密  微信返回的加密数据
     *
     * @param data
     * @param mkey
     * @return
     * @throws Exception
     */
    public static String decryptData(String data, String mkey) throws Exception {
    	
    	Security.addProvider(new BouncyCastleProvider());
        final byte[] decode = Base64.getDecoder().decode(data);
        final String keyStr = DigestUtils.md5Hex(mkey);

        final Key key = new SecretKeySpec(keyStr.getBytes(StandardCharsets.UTF_8), "AES");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding","BC");
        cipher.init(Cipher.DECRYPT_MODE, key);
        final byte[] bytes = cipher.doFinal(decode);
        return new String(bytes, StandardCharsets.UTF_8);
    	
     

    }

    /**
     * 解析微信回调参数
     *
     * @param request
     * @return
     * @throws IOException
     */
    private String parseWeixinCallback(HttpServletRequest request) {
        // 获取微信调用我们notify_url的返回信息
        String result = "";
        ByteArrayOutputStream outSteam = null;
        InputStream inStream = null;
        try {
            inStream = request.getInputStream();
            outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            result = new String(outSteam.toByteArray(), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outSteam != null) {
                    outSteam.close();
                    outSteam = null; // help GC
                }
                if (inStream != null) {
                    inStream.close();
                    inStream = null;// help GC
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 生成签名. 注意，若含有sign_type字段，必须和signType参数保持一致。
     *
     * @param data 待签名数据
     * @param key  API密钥
     * @return 签名
     */
    public String generateSignatureObj(final Map<String, Object> data, String key) {
        if (data == null) {
            log.debug("请求参数map为空");
            return null;
        }
        try {
            Set<String> keySet = data.keySet();
            String[] keyArray = keySet.toArray(new String[keySet.size()]);
            Arrays.sort(keyArray);
            StringBuilder sb = new StringBuilder();
            for (String k : keyArray) {
                if (k.equals("sign")) {
                    continue;
                }
                // 参数值为空，则不参与签名
                if (data.get(k) != null && data.get(k).toString().trim().length() > 0) {
                    sb.append(k).append("=").append(data.get(k).toString().trim()).append("&");
                }
            }
            sb.append("key=").append(key);

            log.debug("微信支付请求签名参数：{}", sb);
            return MD5(sb.toString()).toUpperCase();
        } catch (Exception e) {
            log.error("微信支付签名异常：{}", e);
        }
        return null;
    }


    /**
     * 生成 MD5
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public String generateNonceStr() {
        String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random RANDOM = new SecureRandom();
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }


    public String doRefund(String url, String data, String mch_id) throws Exception {
        //指定读取证书格式为PKCS12(注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的)
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
//        String classPath = this.getClass().getResource("/").getPath();
//        // 指定证书路径
//        String path = classPath+"/cert/apiclient_cert.p12"; //文件名
//        FileInputStream instream = new FileInputStream(new File(path));

        //读取本机存放的PKCS12证书文件
        InputStream instream = getClass().getClassLoader().getResourceAsStream("cert/apiclient_cert.p12");

//        FileInputStream instream = new FileInputStream(new File("C:/Users/Administrator.ZYNO1/Desktop/1548343411_20190815_cert/apiclient_cert.p12"));
        //比如安装在D:/pkcs12/apiclient_cert.p12情况下，就可以写成如下语句
        //FileInputStream instream = new FileInputStream(new File("D:/pkcs12/apiclient_cert.p12"));
        try {
            //指定PKCS12的密码(商户ID)
            keyStore.load(instream,mch_id.toCharArray());
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
        //指定TLS版本
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        //设置httpclient的SSLSocketFactory
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }
public  static void main (String [] args)throws Exception{
    String callbackXml = "<xml><return_code>SUCCESS</return_code><appid><![CDATA[wxcb69193aaf710be7]]></appid><mch_id><![CDATA[1548343411]]></mch_id><nonce_str><![CDATA[ac7464f3277442216f88baa1de760287]]></nonce_str><req_info><![CDATA[sy+JtGI7hcJcCxvBiOAE7j5fzJTkKevEynsWFz2UdnX1SNz/5egxAkL9OuiBkURpShQwWqPMLht5xKpezI1dQB3qLVVztm5HATavEXzQCzXrpt3Ts8hWMjoCmQxIam9eigeAvHIZ7j2bO0yg22oJA5oIISCmx4KQ5UZZhmDZYgoHI0eoZuChL+ZaNinCt1unm9Fbdjs5GAL/byMisCmKDID7NO/iTzX5p6MngWXkeaZ2TBfAhgg/SmDG2rWKroUzEzWdR4sNV/7X4d2CzeVQc4ZUWtnnMRn0sDbLBmy5Rnno2nGi/nkeHMmrr9FC6So1X2vNyu9J2pu+zGwgTuTjZyKhRIjVsos6m/DVzyEBQo5coAOHsEPBsyqX2BINstYn1VB4z6czJuMuFo+fwRZ5zcfoX99x4YbrAKCGTUFmtgKR5K+DfnBusgzc7SjTbSY4COXdQwlhFv7FoxCy1/EwhB87GpQBtX5907wcedNXtVGhrNByqngYfZIODiC9qrAkm9L8h4gnYRvQJRhOS/LWKo3w0waKrvej36x51BAl8AXazGyjo4VC93yRDTwoQEpTNzNRjRApf3nMvccWbBarBOt+By5wLq6l/3D2QUCMe57553ZT/17bTAHncvScLK+7XbO19D6Spyn2BNvEBvDCKKVzYJ/GeHSG1NKVB/rqF01Uo8+TBAx9BRj4GRojXJGz4HB14HZhLAeboMK1bxv+1Kd2ahMzjnXXqOErTTz6TM2/WxuWP2KkEipKqyYYD8Hipfs0YU93TL51s582+pDxyJAimFOl6uXnaLy7psXtMXuzExGOF6RG3CZ9G4HHIlR5S5ZHgC9W1Rp2uMz/eQlt4l43IupbNcKan/pNrY22HWt5a1rGJd3Yftf+mdYMZJlnupQyMy/uArCB8TftLaeDnxvH0XdyWzDn1vXVruVe9LzQc3yUeHgXGN4CykFNF05RP2RGzZDTucyK61BKKdcsF8p8FyZTWjpb/0L96ciDfok0536G9pEHl0hjQAaG7Zdbe7xzvJx3XdzjfSTCieRoPoMcc6YhbviOj0+xLHRF9OyWr9B7dUjHPCZpwnUXp/wmargK/tAt3ETq8r2plhLvXQ==]]></req_info></xml> ";
    System.out.println(callbackXml);
    System.out.println("==============================================");
    WechatRefundCallBack wechatRefundCallBack = XmlUtils.xml2Bean(callbackXml, WechatRefundCallBack.class);
    String result =  decryptData(wechatRefundCallBack.getReq_info(), "ShwqJ7216FLnxO6skRBD7HfLZcVzSMXR");
    
    System.out.println(result);
 
     
}

}
